Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

333
Vistas
¿Cómo haría coincidir todos los "bloques de cotización" en un correo electrónico de texto sin formato en PHP PCRE?

Estoy tratando de hacer coincidir todas las comillas en el siguiente mensaje de correo electrónico de ejemplo:

 > Don't forget to buy eggiweggs on the way home. I shall not. > Also remember to brush your shoes. Will do. > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids. I see what you mean. They sure make a mess.

Eso significa que quiero hacer coincidir estas tres cadenas:

 > Don't forget to buy eggiweggs on the way home.

Y:

 > Also remember to brush your shoes.

Y:

 > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids.

No entiendo cómo puedo hacer esto, ya que si uso el indicador s para abarcar varias líneas, lo cual es necesario para esto, no puedo referirme a ^ y $ para indicar "comienzo de línea" y "final de línea" - - en cambio, significan "comienzo de cadena" y "final de cadena".

Entonces, si hago: #^(> .+?)$#us , coincidirá con todo después/con la primera cita.

Y si lo hago: #^(> .+?)$#um , solo coincidirá con la primera línea de la primera cita y nada más.

Esto es frustrante. Realmente no tengo idea de cómo resolverlo. Busqué en línea antes de preguntar y no encontré ninguna página, ni siquiera remotamente relevante, como de costumbre.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Con preg_match_all :

 preg_match_all('~^> .*(?:\R> .*)*~m', $txt, $matches); $result = $matches[0];

(donde \R es un alias para varias secuencias de nueva línea)


Con preg_split :

 $result = preg_split('~^(?!> ).*\R?~m', $txt, -1, PREG_SPLIT_NO_EMPTY);

que divide la cadena en cada línea que no comienza con > . Para recortar la nueva línea al final de cada bloque, puede comenzar este patrón con \R? => ~\R?^(?!> ).*\R?~m o algo así ~(?:\R?^(?!> ).*)+\R?~m para tomar eventualmente varias líneas en un momento.


Acerca de \R :
\R es por defecto un alias para (?>\r\n|\n|\x0b|\f|\r|\x85) (cualquier secuencia de caracteres de 8 bits que no sea utf8 para una nueva línea). En modo utf8, con el modificador u o comenzando el patrón con (*UTF8)(*BSR_UNICODE) , se agregan a la lista otros dos caracteres fuera del rango ASCII: el separador de línea (U+2028), el separador de párrafo (U +2029).
Es útil cuando no sabe qué secuencia de nueva línea se usa en la cadena, pero es más lento que escribir la secuencia de nueva línea exacta si la conoce. Puede restringir \R a (?>\r\n|\n|\r) con la directiva (*BSR_ANYCRLF) al comienzo del patrón.

over 4 years ago · Santiago Trujillo Denunciar

0

Mi idea es dividir la cadena en función de los saltos de línea. tal vez esto te ayude?

 foreach(explode("\n", $string) as $key=>$val) { if(preg_match('/^(>.*)$/', $val, $match)) echo $match[1] . PHP_EOL; }

producción:

 > Don't forget to buy eggiweggs on the way home. > Also remember to brush your shoes. > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids.

editar: probé algo más ... pero no es perfecto

 preg_match_all("/(>[^\n]+)/sm", $string, $match); print_r($match);

producción

 Array ( [0] => > Don't forget to buy eggiweggs on the way home. [1] => > Also remember to brush your shoes. [2] => > > > And clean up after the pigs. [3] => > > But I have no pigs. [4] => > Yes, you do. Your kids. )
over 4 years ago · Santiago Trujillo Denunciar

0

Hacer coincidir explícitamente el final de la cita

En lugar de intentar modificar el comportamiento codicioso/no codicioso, es más fácil resolver los problemas de expresiones regulares si puede hacer coincidir algo inequívoco al comienzo/final del partido.

Cuando un bloque entre comillas continúa en varias líneas, los últimos caracteres de la línea son [nueva línea] + > , cuando un bloque entre comillas termina, los últimos caracteres de la cita son [nueva línea] + [no >] - Esta lógica/patrón permite encontrar el bloques enteros citados.

De esta lógica llegamos a:

 /(> .+?)\n[^>]/s

Este es:

 / # Regex start delimiter ( # Start of capturing group > # Literal > # Literal space . # Any character, including newlines +? # At least once, none-greedy match ) # End of Capturing group \n # Newline [^>] # anything _except_ a literal > / # Regex end delimiter s # PCRE_DOTALL flag (makes . also match newlines)

El uso de una coincidencia no codiciosa aquí evita que la expresión regular coincida con el inicio de la primera cita hasta el final de la última cita.

Elegir entre (o combinar) PCRE_DOTALL y PCRE_MULTILINE depende de la estrategia empleada; aquí la intención es solo modificar el comportamiento de . . Más info en los documentos .

Si el texto fuente proviene de Windows, es posible que desee usar \R (como se indica en una respuesta diferente).

Demostración

 <?php $input = <<<STUFF > Don't forget to buy eggiweggs on the way home. I shall not. > Also remember to brush your shoes. Will do. > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids. I see what you mean. They sure make a mess. STUFF; $regex = "/(> .+?)\n[^>]/s"; preg_match_all($regex, $input, $matches); print_r($matches);

Resultados en:

 Array ( [0] => Array ( [0] => > Don't forget to buy eggiweggs on the way home. [1] => > Also remember to brush your shoes. [2] => > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids. ) [1] => Array ( [0] => > Don't forget to buy eggiweggs on the way home. [1] => > Also remember to brush your shoes. [2] => > > > And clean up after the pigs. > > But I have no pigs. > Yes, you do. Your kids. ) )

¿Por qué no funcionan los intentos en la pregunta?

Así que si lo hago: #^(> .+?)$#us

El modificador s solo afecta a ^ y $ .

Esta expresión regular está anclada al inicio y al final de cada línea (hace una coincidencia no codiciosa, pero el . no coincidirá con una nueva línea de todos modos), por lo tanto, coincide con cada línea citada individualmente.

Y si lo hago: #^(> .+?)$#um

El modificador m solo afecta a . .

No tiene efecto en ^ o $ , por lo que, como se indica en la pregunta, esto puede producir como máximo una coincidencia.

Las banderas no se excluyen mutuamente y se pueden usar en combinación.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda